/*
 * Copyright 2002-2019 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.springframework.aop.framework.autoproxy;

import java.lang.reflect.Constructor;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

import org.aopalliance.aop.Advice;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import org.springframework.aop.Advisor;
import org.springframework.aop.Pointcut;
import org.springframework.aop.TargetSource;
import org.springframework.aop.framework.AopInfrastructureBean;
import org.springframework.aop.framework.ProxyFactory;
import org.springframework.aop.framework.ProxyProcessorSupport;
import org.springframework.aop.framework.adapter.AdvisorAdapterRegistry;
import org.springframework.aop.framework.adapter.GlobalAdvisorAdapterRegistry;
import org.springframework.aop.target.SingletonTargetSource;
import org.springframework.beans.BeansException;
import org.springframework.beans.PropertyValues;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.config.SmartInstantiationAwareBeanPostProcessor;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;

/**
 * {@link org.springframework.beans.factory.config.BeanPostProcessor} implementation
 * that wraps each eligible bean with an AOP proxy, delegating to specified interceptors
 * before invoking the bean itself.
 *
 * <p>This class distinguishes between "common" interceptors: shared for all proxies it
 * creates, and "specific" interceptors: unique per bean instance. There need not be any
 * common interceptors. If there are, they are set using the interceptorNames property.
 * As with {@link org.springframework.aop.framework.ProxyFactoryBean}, interceptors names
 * in the current factory are used rather than bean references to allow correct handling
 * of prototype advisors and interceptors: for example, to support stateful mixins.
 * Any advice type is supported for {@link #setInterceptorNames "interceptorNames"} entries.
 *
 * <p>Such auto-proxying is particularly useful if there's a large number of beans that
 * need to be wrapped with similar proxies, i.e. delegating to the same interceptors.
 * Instead of x repetitive proxy definitions for x target beans, you can register
 * one single such post processor with the bean factory to achieve the same effect.
 *
 * <p>Subclasses can apply any strategy to decide if a bean is to be proxied, e.g. by type,
 * by name, by definition details, etc. They can also return additional interceptors that
 * should just be applied to the specific bean instance. A simple concrete implementation is
 * {@link BeanNameAutoProxyCreator}, identifying the beans to be proxied via given names.
 *
 * <p>Any number of {@link TargetSourceCreator} implementations can be used to create
 * a custom target source: for example, to pool prototype objects. Auto-proxying will
 * occur even if there is no advice, as long as a TargetSourceCreator specifies a custom
 * {@link org.springframework.aop.TargetSource}. If there are no TargetSourceCreators set,
 * or if none matches, a {@link org.springframework.aop.target.SingletonTargetSource}
 * will be used by default to wrap the target bean instance.
 *
 * @author Juergen Hoeller
 * @author Rod Johnson
 * @author Rob Harrop
 * @since 13.10.2003
 * @see #setInterceptorNames
 * @see #getAdvicesAndAdvisorsForBean
 * @see BeanNameAutoProxyCreator
 * @see DefaultAdvisorAutoProxyCreator
 */
@SuppressWarnings("serial")
public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
		implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware {

	/**
	 * Convenience constant for subclasses: Return value for "do not proxy".
	 * @see #getAdvicesAndAdvisorsForBean
	 */
	@Nullable
	protected static final Object[] DO_NOT_PROXY = null;

	/**
	 * Convenience constant for subclasses: Return value for
	 * "proxy without additional interceptors, just the common ones".
	 * @see #getAdvicesAndAdvisorsForBean
	 */
	protected static final Object[] PROXY_WITHOUT_ADDITIONAL_INTERCEPTORS = new Object[0];


	/** Logger available to subclasses. */
	protected final Log logger = LogFactory.getLog(getClass());

	/** Default is global AdvisorAdapterRegistry. */
	private AdvisorAdapterRegistry advisorAdapterRegistry = GlobalAdvisorAdapterRegistry.getInstance();

	/**
	 * Indicates whether or not the proxy should be frozen. Overridden from super
	 * to prevent the configuration from becoming frozen too early.
	 */
	private boolean freezeProxy = false;

	/** Default is no common interceptors. */
	private String[] interceptorNames = new String[0];

	private boolean applyCommonInterceptorsFirst = true;

	@Nullable
	private TargetSourceCreator[] customTargetSourceCreators;

	@Nullable
	private BeanFactory beanFactory;

	private final Set<String> targetSourcedBeans = Collections.newSetFromMap(new ConcurrentHashMap<>(16));

	private final Map<Object, Object> earlyProxyReferences = new ConcurrentHashMap<>(16);

	private final Map<Object, Class<?>> proxyTypes = new ConcurrentHashMap<>(16);

	private final Map<Object, Boolean> advisedBeans = new ConcurrentHashMap<>(256);


	/**
	 * Set whether or not the proxy should be frozen, preventing advice
	 * from being added to it once it is created.
	 * <p>Overridden from the super class to prevent the proxy configuration
	 * from being frozen before the proxy is created.
	 */
	@Override
	public void setFrozen(boolean frozen) {
		this.freezeProxy = frozen;
	}

	@Override
	public boolean isFrozen() {
		return this.freezeProxy;
	}

	/**
	 * Specify the {@link AdvisorAdapterRegistry} to use.
	 * <p>Default is the global {@link AdvisorAdapterRegistry}.
	 * @see org.springframework.aop.framework.adapter.GlobalAdvisorAdapterRegistry
	 */
	public void setAdvisorAdapterRegistry(AdvisorAdapterRegistry advisorAdapterRegistry) {
		this.advisorAdapterRegistry = advisorAdapterRegistry;
	}

	/**
	 * Set custom {@code TargetSourceCreators} to be applied in this order.
	 * If the list is empty, or they all return null, a {@link SingletonTargetSource}
	 * will be created for each bean.
	 * <p>Note that TargetSourceCreators will kick in even for target beans
	 * where no advices or advisors have been found. If a {@code TargetSourceCreator}
	 * returns a {@link TargetSource} for a specific bean, that bean will be proxied
	 * in any case.
	 * <p>{@code TargetSourceCreators} can only be invoked if this post processor is used
	 * in a {@link BeanFactory} and its {@link BeanFactoryAware} callback is triggered.
	 * @param targetSourceCreators the list of {@code TargetSourceCreators}.
	 * Ordering is significant: The {@code TargetSource} returned from the first matching
	 * {@code TargetSourceCreator} (that is, the first that returns non-null) will be used.
	 */
	public void setCustomTargetSourceCreators(TargetSourceCreator... targetSourceCreators) {
		this.customTargetSourceCreators = targetSourceCreators;
	}

	/**
	 * Set the common interceptors. These must be bean names in the current factory.
	 * They can be of any advice or advisor type Spring supports.
	 * <p>If this property isn't set, there will be zero common interceptors.
	 * This is perfectly valid, if "specific" interceptors such as matching
	 * Advisors are all we want.
	 */
	public void setInterceptorNames(String... interceptorNames) {
		this.interceptorNames = interceptorNames;
	}

	/**
	 * Set whether the common interceptors should be applied before bean-specific ones.
	 * Default is "true"; else, bean-specific interceptors will get applied first.
	 */
	public void setApplyCommonInterceptorsFirst(boolean applyCommonInterceptorsFirst) {
		this.applyCommonInterceptorsFirst = applyCommonInterceptorsFirst;
	}

	@Override
	public void setBeanFactory(BeanFactory beanFactory) {
		this.beanFactory = beanFactory;
	}

	/**
	 * Return the owning {@link BeanFactory}.
	 * May be {@code null}, as this post-processor doesn't need to belong to a bean factory.
	 */
	@Nullable
	protected BeanFactory getBeanFactory() {
		return this.beanFactory;
	}


	@Override
	@Nullable
	public Class<?> predictBeanType(Class<?> beanClass, String beanName) {
		if (this.proxyTypes.isEmpty()) {
			return null;
		}
		Object cacheKey = getCacheKey(beanClass, beanName);
		return this.proxyTypes.get(cacheKey);
	}

	@Override
	@Nullable
	public Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, String beanName) {
		return null;
	}

	@Override
	public Object getEarlyBeanReference(Object bean, String beanName) {
		Object cacheKey = getCacheKey(bean.getClass(), beanName);
		this.earlyProxyReferences.put(cacheKey, bean);
		return wrapIfNecessary(bean, beanName, cacheKey);
	}

	/**
	 * 在目标Bean实例化之前进行处理，可用于提前创建代理对象，替代默认的实例化过程。
	 * 这是Spring AOP实现的关键扩展点，允许在Bean生命周期的早期介入并应用切面逻辑。
	 *
	 * 执行流程：
	 * 1. 检查缓存状态，避免重复处理已处理过的Bean
	 * 2. 排除基础设施类和需要跳过的Bean
	 * 3. 尝试为Bean创建自定义TargetSource（目标源）
	 * 4. 若存在自定义TargetSource，创建代理对象并返回
	 * 5. 若无需干预实例化过程，则返回null，让Spring继续默认的实例化流程
	 *
	 * @param beanClass Bean的Class对象
	 * @param beanName Bean的名称
	 * @return 若返回非null对象，则表示已创建代理并替代默认实例化；否则返回null
	 */
	@Override
	public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {
		// 生成缓存键，用于标识当前Bean的处理状态
		Object cacheKey = getCacheKey(beanClass, beanName);

		// 检查条件：
		// 1. beanName为空（罕见情况）
		// 2. 或beanName不在targetSourcedBeans集合中（即尚未为该Bean创建自定义TargetSource）
		if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
			// 检查缓存中是否已有该Bean的处理结果
			// advisedBeans存储已处理Bean的状态：TRUE表示已创建代理，FALSE表示无需代理
			if (this.advisedBeans.containsKey(cacheKey)) {
				return null; // 直接返回null，避免重复处理
			}

			// 判断是否为基础设施类（如Advisor、Pointcut等）或应跳过的类
			// 若是，则标记为不需要代理并返回null
			if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
				this.advisedBeans.put(cacheKey, Boolean.FALSE);
				return null;
			}
		}

		// 尝试为当前Bean获取自定义TargetSource
		// TargetSource负责管理目标对象的创建和获取方式（如单例、原型、池化等）
		TargetSource targetSource = getCustomTargetSource(beanClass, beanName);

		// 若成功获取到自定义TargetSource，创建代理对象
		if (targetSource != null) {
			// 将beanName添加到targetSourcedBeans集合，标记已为该Bean创建TargetSource
			if (StringUtils.hasLength(beanName)) {
				this.targetSourcedBeans.add(beanName);
			}

			// 获取适用于该Bean的增强器（Advice）和切面（Advisor）
			Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);

			// 创建代理对象
			// 使用指定的TargetSource、增强器和代理工厂创建AOP代理
			Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);

			// 缓存代理对象的类型，避免后续重复创建
			this.proxyTypes.put(cacheKey, proxy.getClass());

			// 返回代理对象，将跳过Spring的默认实例化过程
			return proxy;
		}

		// 返回null表示不干预默认的实例化过程，Spring将继续创建原始Bean实例
		return null;
	}
	@Override
	public boolean postProcessAfterInstantiation(Object bean, String beanName) {
		return true;
	}

	@Override
	public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
		return pvs;
	}

	@Override
	public Object postProcessBeforeInitialization(Object bean, String beanName) {
		return bean;
	}

	/**
	 * 在 Bean 初始化完成后，根据子类的判断逻辑决定是否为该 Bean 创建 AOP 代理。
	 * 该方法会检查 Bean 是否需要被代理，如果需要则应用配置的拦截器链创建代理对象，
	 * 否则直接返回原始 Bean 实例。
	 *
	 * <p>此方法是 Spring AOP 自动代理机制的核心实现之一，通过 BeanPostProcessor 接口在 Bean
	 * 生命周期的最后阶段介入，确保代理对象在被应用代码使用前已经正确创建。
	 *
	 * <p>执行流程：
	 * <ol>
	 *   <li>生成当前 Bean 的缓存键，用于标识该 Bean 是否需要代理</li>
	 *   <li>检查该 Bean 是否已在早期代理引用中处理过（解决循环依赖问题）</li>
	 *   <li>若未处理过，调用 wrapIfNecessary 方法判断是否需要代理：
	 *     <ul>
	 *       <li>通过 getAdvicesAndAdvisorsForBean 方法获取匹配的增强器</li>
	 *       <li>若存在增强器，创建包含这些增强器的 AOP 代理</li>
	 *       <li>若不存在增强器，直接返回原始 Bean</li>
	 *     </ul>
	 *   </li>
	 *   <li>若已处理过（循环依赖场景），直接返回原始 Bean</li>
	 * </ol>
	 *
	 * <p>循环依赖处理：
	 * <ul>
	 *   <li>对于存在循环依赖的 Bean，早期代理会在属性注入阶段创建</li>
	 *   <li>通过 earlyProxyReferences 缓存标记已创建早期代理的 Bean，避免重复代理</li>
	 *   <li>早期代理仅包含已解析的增强器，可能不完整（如基于注解的增强器）</li>
	 * </ul>
	 *
	 * <p>代理创建策略：
	 * <ul>
	 *   <li>若 Bean 实现了接口，默认使用 JDK 动态代理</li>
	 *   <li>若 Bean 为具体类，使用 CGLIB 代理</li>
	 *   <li>可通过 proxyTargetClass 属性强制使用 CGLIB 代理</li>
	 * </ul>
	 *
	 * @param bean     初始化完成的 Bean 实例（可能为 null）
	 * @param beanName Bean 的名称
	 * @return 原始 Bean 或其 AOP 代理对象
	 *
	 * @see #getAdvicesAndAdvisorsForBean - 确定 Bean 是否需要代理及获取增强器的核心方法
	 * @see #wrapIfNecessary - 创建代理的实际实现方法
	 * @see #earlyProxyReferences - 存储早期代理引用的缓存
	 * @see org.springframework.aop.framework.ProxyFactory - AOP 代理创建工厂
	 */
	@Override
	public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
		if (bean != null) {
			// 生成用于缓存的唯一键，基于 Bean 类型和名称
			Object cacheKey = getCacheKey(bean.getClass(), beanName);
			// 检查该 Bean 是否已在早期代理阶段处理过
			// 若是，则跳过代理创建（循环依赖场景）
			if (this.earlyProxyReferences.remove(cacheKey) != bean) {
				// 对需要代理的 Bean 应用增强器并创建代理
				return wrapIfNecessary(bean, beanName, cacheKey);
			}
		}
		// Bean 为 null 或已处理过，直接返回原始实例
		return bean;
	}

	/**
	 * Build a cache key for the given bean class and bean name.
	 * <p>Note: As of 4.2.3, this implementation does not return a concatenated
	 * class/name String anymore but rather the most efficient cache key possible:
	 * a plain bean name, prepended with {@link BeanFactory#FACTORY_BEAN_PREFIX}
	 * in case of a {@code FactoryBean}; or if no bean name specified, then the
	 * given bean {@code Class} as-is.
	 * @param beanClass the bean class
	 * @param beanName the bean name
	 * @return the cache key for the given class and name
	 */
	protected Object getCacheKey(Class<?> beanClass, @Nullable String beanName) {
		if (StringUtils.hasLength(beanName)) {
			return (FactoryBean.class.isAssignableFrom(beanClass) ?
					BeanFactory.FACTORY_BEAN_PREFIX + beanName : beanName);
		}
		else {
			return beanClass;
		}
	}

	/**
	 * 根据条件判断是否需要为给定的 Bean 创建 AOP 代理。
	 * 该方法会检查 Bean 是否符合代理条件，若符合则应用配置的拦截器创建代理对象，
	 * 否则直接返回原始 Bean 实例。这是 Spring AOP 自动代理机制的核心实现方法之一。
	 *
	 * <p>代理决策逻辑基于以下几个维度：
	 * <ol>
	 *   <li>Bean 是否已被标记为使用特殊 TargetSource（通过 targetSourcedBeans 判断）</li>
	 *   <li>Bean 是否已被缓存为不需要代理（通过 advisedBeans 判断）</li>
	 *   <li>Bean 是否属于基础设施类（如 BeanPostProcessor）或应被跳过的类</li>
	 *   <li>Bean 是否存在匹配的增强器（通过 getAdvicesAndAdvisorsForBean 判断）</li>
	 * </ol>
	 *
	 * <p>执行流程：
	 * <ol>
	 *   <li>检查 Bean 是否已配置特殊 TargetSource，若是则直接返回原始 Bean</li>
	 *   <li>检查 Bean 是否已被缓存为不需要代理，若是则直接返回原始 Bean</li>
	 *   <li>检查 Bean 是否为基础设施类或应被跳过的类，若是则标记并返回原始 Bean</li>
	 *   <li>获取适用于该 Bean 的增强器列表：
	 *     <ul>
	 *       <li>若存在增强器，创建包含这些增强器的 AOP 代理</li>
	 *       <li>若不存在增强器，标记并返回原始 Bean</li>
	 *     </ul>
	 *   </li>
	 *   <li>缓存代理类型信息（用于后续类型检查）</li>
	 * </ol>
	 *
	 * <p>关键数据结构：
	 * <ul>
	 *   <li>targetSourcedBeans：存储需要特殊 TargetSource 的 Bean 名称</li>
	 *   <li>advisedBeans：缓存 Bean 是否需要代理的结果（Boolean.TRUE/FALSE）</li>
	 *   <li>proxyTypes：缓存 Bean 对应的代理类型</li>
	 * </ul>
	 *
	 * <p>注意事项：
	 * <ul>
	 *   <li>增强器匹配逻辑由子类实现的 getAdvicesAndAdvisorsForBean 方法决定</li>
	 *   <li>基础设施类（如 BeanPostProcessor）不会被代理，避免代理链循环</li>
	 *   <li>代理创建后会缓存代理类型，用于后续类型匹配检查</li>
	 * </ul>
	 *
	 * @param bean     原始 Bean 实例
	 * @param beanName Bean 的名称
	 * @param cacheKey 用于元数据访问的缓存键
	 * @return 代理对象（如果需要代理）或原始 Bean 实例
	 *
	 * @see #getAdvicesAndAdvisorsForBean - 获取 Bean 匹配的增强器列表
	 * @see #createProxy - 创建 AOP 代理的方法
	 * @see #isInfrastructureClass - 判断 Bean 是否为基础设施类
	 * @see #shouldSkip - 判断 Bean 是否应被跳过代理
	 * @see org.springframework.aop.TargetSource - 目标源接口
	 * @see org.springframework.aop.framework.ProxyFactory - 代理工厂
	 */
	protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
		// 检查 Bean 是否已配置特殊 TargetSource（如池化或自定义作用域）
		// 这类 Bean 已通过其他机制处理，直接返回原始实例
		if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
			return bean;
		}

		// 检查 Bean 是否已被缓存为不需要代理
		if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
			return bean;
		}

		// 检查 Bean 是否为基础设施类（如 BeanPostProcessor）或应被跳过的类
		// 这类 Bean 通常参与框架内部逻辑，不适合被代理
		if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
			this.advisedBeans.put(cacheKey, Boolean.FALSE);
			return bean;
		}

		// 获取适用于该 Bean 的增强器列表
		//获取到需要的AdvicesBea
		Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
		// DO_NOT_PROXY 是一个特殊常量，表示不需要代理

		if (specificInterceptors != DO_NOT_PROXY) {
			// 存在匹配的增强器，创建 AOP 代理
			this.advisedBeans.put(cacheKey, Boolean.TRUE);

			// 创建代理对象，使用 SingletonTargetSource 包装原始 Bean
			Object proxy = createProxy(
					bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));

			// 缓存代理类型，用于后续类型检查
			this.proxyTypes.put(cacheKey, proxy.getClass());
			return proxy;
		}

		// 没有匹配的增强器，标记为不需要代理并返回原始 Bean
		this.advisedBeans.put(cacheKey, Boolean.FALSE);
		return bean;
	}
	/**
	 * 判断给定的Bean类是否属于基础设施类，这类Bean通常是AOP框架自身的组件，
	 * 不需要被代理或织入额外的切面逻辑。
	 *
	 * 基础设施类的典型示例包括：
	 * - Advice（通知）：如BeforeAdvice、AfterAdvice等增强逻辑
	 * - Pointcut（切点）：定义切入点表达式的组件
	 * - Advisor（切面）：组合Pointcut和Advice的完整切面定义
	 * - AopInfrastructureBean：Spring AOP基础设施的标记接口实现类
	 *
	 * 此方法的返回值会影响Bean的处理流程：
	 * - 若返回true，框架会跳过对该Bean的自动代理过程
	 * - 若返回false，框架会继续评估是否需要为该Bean创建代理
	 *
	 * @param beanClass 待检查的Bean类
	 * @return 如果是基础设施类返回true，否则返回false
	 * @see org.aopalliance.aop.Advice
	 * @see org.springframework.aop.Pointcut
	 * @see org.springframework.aop.Advisor
	 * @see org.springframework.aop.framework.AopInfrastructureBean
	 * @see #shouldSkip
	 */
	protected boolean isInfrastructureClass(Class<?> beanClass) {
		// 判断beanClass是否属于以下任意一种类型：
		// 1. Advice接口的实现类（如MethodInterceptor）
		// 2. Pointcut接口的实现类（如RegexpMethodPointcut）
		// 3. Advisor接口的实现类（如DefaultPointcutAdvisor）
		// 4. AopInfrastructureBean接口的实现类（如ProxyFactoryBean）
		boolean retVal = Advice.class.isAssignableFrom(beanClass) ||
				Pointcut.class.isAssignableFrom(beanClass) ||
				Advisor.class.isAssignableFrom(beanClass) ||
				AopInfrastructureBean.class.isAssignableFrom(beanClass);

		// 当确定为基础设施类且启用了TRACE日志时，记录跳过代理的信息
		// 这有助于调试AOP代理的创建过程
		if (retVal && logger.isTraceEnabled()) {
			logger.trace("Did not attempt to auto-proxy infrastructure class [" + beanClass.getName() + "]");
		}

		return retVal;
	}
	/**
	 * Subclasses should override this method to return {@code true} if the
	 * given bean should not be considered for auto-proxying by this post-processor.
	 * <p>Sometimes we need to be able to avoid this happening, e.g. if it will lead to
	 * a circular reference or if the existing target instance needs to be preserved.
	 * This implementation returns {@code false} unless the bean name indicates an
	 * "original instance" according to {@code AutowireCapableBeanFactory} conventions.
	 * @param beanClass the class of the bean
	 * @param beanName the name of the bean
	 * @return whether to skip the given bean
	 * @see org.springframework.beans.factory.config.AutowireCapableBeanFactory#ORIGINAL_INSTANCE_SUFFIX
	 */
	protected boolean shouldSkip(Class<?> beanClass, String beanName) {
		return AutoProxyUtils.isOriginalInstance(beanName, beanClass);
	}

	/**
	 * 为指定 Bean 创建自定义 TargetSource 对象。
	 * 该方法会遍历所有已注册的 TargetSourceCreator，尝试为目标 Bean 生成特殊的 TargetSource。
	 * 如果没有找到合适的 TargetSourceCreator 或生成失败，则返回 null，表示使用默认代理创建策略。就是说不在这里进行定制化的代理
	 *
	 * <p>TargetSource 是 Spring AOP 中的核心组件，负责确定代理对象的目标实例。
	 * 通过自定义 TargetSource，可以实现诸如实例池化、热交换、自定义作用域等高级特性。
	 *
	 * <p>执行流程：
	 * <ol>
	 *   <li>检查是否存在自定义 TargetSourceCreator 列表</li>
	 *   <li>验证 BeanFactory 已初始化且包含指定名称的 Bean</li>
	 *   <li>按顺序调用每个 TargetSourceCreator 的 getTargetSource 方法</li>
	 *   <li>若某个 Creator 返回非空 TargetSource，则立即返回该对象</li>
	 *   <li>若所有 Creator 均返回 null，则返回 null</li>
	 * </ol>
	 *
	 * <p>注意事项：
	 * <ul>
	 *   <li>直接注册的单例 Bean 通常不会使用复杂的 TargetSource</li>
	 *   <li>子类可重写此方法以实现不同的 TargetSource 创建逻辑</li>
	 *   <li>返回 null 是正常情况，表示使用默认代理策略</li>
	 * </ul>
	 *
	 * @param beanClass 待创建 TargetSource 的 Bean 类型
	 * @param beanName  待创建 TargetSource 的 Bean 名称
	 * @return 适用于该 Bean 的自定义 TargetSource，若没有则返回 null
	 *
	 * @see #setCustomTargetSourceCreators
	 * @see org.springframework.aop.TargetSource
	 * @see org.springframework.aop.framework.autoproxy.TargetSourceCreator
	 * @see org.springframework.aop.framework.ProxyFactory
	 */
	@Nullable
	protected TargetSource getCustomTargetSource(Class<?> beanClass, String beanName) {
		// 直接注册的单例 Bean 通常不需要特殊的 TargetSource
		if (this.customTargetSourceCreators != null &&
				this.beanFactory != null && this.beanFactory.containsBean(beanName)) {
			// 遍历所有注册的 TargetSourceCreator
			for (TargetSourceCreator tsc : this.customTargetSourceCreators) {
				// 尝试为当前 Bean 创建 TargetSource
				TargetSource ts = tsc.getTargetSource(beanClass, beanName);
				if (ts != null) {
					// 找到匹配的 TargetSource，记录日志并返回
					if (logger.isTraceEnabled()) {
						logger.trace("TargetSourceCreator [" + tsc +
								"] found custom TargetSource for bean with name '" + beanName + "'");
					}
					return ts;
				}
			}
		}

		// 没有找到自定义 TargetSource，返回 null 表示使用默认策略
		return null;
	}

	/**
	 * Create an AOP proxy for the given bean.
	 * @param beanClass the class of the bean
	 * @param beanName the name of the bean
	 * @param specificInterceptors the set of interceptors that is
	 * specific to this bean (may be empty, but not null)
	 * @param targetSource the TargetSource for the proxy,
	 * already pre-configured to access the bean
	 * @return the AOP proxy for the bean
	 * @see #buildAdvisors
	 */
	protected Object createProxy(Class<?> beanClass, @Nullable String beanName,
			@Nullable Object[] specificInterceptors, TargetSource targetSource) {

		if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
			AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
		}

		ProxyFactory proxyFactory = new ProxyFactory();
		proxyFactory.copyFrom(this);

		if (!proxyFactory.isProxyTargetClass()) {
			if (shouldProxyTargetClass(beanClass, beanName)) {
				proxyFactory.setProxyTargetClass(true);
			}
			else {
				evaluateProxyInterfaces(beanClass, proxyFactory);
			}
		}

		Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
		proxyFactory.addAdvisors(advisors);
		proxyFactory.setTargetSource(targetSource);
		customizeProxyFactory(proxyFactory);

		proxyFactory.setFrozen(this.freezeProxy);
		if (advisorsPreFiltered()) {
			proxyFactory.setPreFiltered(true);
		}

		return proxyFactory.getProxy(getProxyClassLoader());
	}

	/**
	 * Determine whether the given bean should be proxied with its target class rather than its interfaces.
	 * <p>Checks the {@link AutoProxyUtils#PRESERVE_TARGET_CLASS_ATTRIBUTE "preserveTargetClass" attribute}
	 * of the corresponding bean definition.
	 * @param beanClass the class of the bean
	 * @param beanName the name of the bean
	 * @return whether the given bean should be proxied with its target class
	 * @see AutoProxyUtils#shouldProxyTargetClass
	 */
	protected boolean shouldProxyTargetClass(Class<?> beanClass, @Nullable String beanName) {
		return (this.beanFactory instanceof ConfigurableListableBeanFactory &&
				AutoProxyUtils.shouldProxyTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName));
	}

	/**
	 * Return whether the Advisors returned by the subclass are pre-filtered
	 * to match the bean's target class already, allowing the ClassFilter check
	 * to be skipped when building advisors chains for AOP invocations.
	 * <p>Default is {@code false}. Subclasses may override this if they
	 * will always return pre-filtered Advisors.
	 * @return whether the Advisors are pre-filtered
	 * @see #getAdvicesAndAdvisorsForBean
	 * @see org.springframework.aop.framework.Advised#setPreFiltered
	 */
	protected boolean advisorsPreFiltered() {
		return false;
	}

	/**
	 * Determine the advisors for the given bean, including the specific interceptors
	 * as well as the common interceptor, all adapted to the Advisor interface.
	 * @param beanName the name of the bean
	 * @param specificInterceptors the set of interceptors that is
	 * specific to this bean (may be empty, but not null)
	 * @return the list of Advisors for the given bean
	 */
	protected Advisor[] buildAdvisors(@Nullable String beanName, @Nullable Object[] specificInterceptors) {
		// Handle prototypes correctly...
		Advisor[] commonInterceptors = resolveInterceptorNames();

		List<Object> allInterceptors = new ArrayList<>();
		if (specificInterceptors != null) {
			allInterceptors.addAll(Arrays.asList(specificInterceptors));
			if (commonInterceptors.length > 0) {
				if (this.applyCommonInterceptorsFirst) {
					allInterceptors.addAll(0, Arrays.asList(commonInterceptors));
				}
				else {
					allInterceptors.addAll(Arrays.asList(commonInterceptors));
				}
			}
		}
		if (logger.isTraceEnabled()) {
			int nrOfCommonInterceptors = commonInterceptors.length;
			int nrOfSpecificInterceptors = (specificInterceptors != null ? specificInterceptors.length : 0);
			logger.trace("Creating implicit proxy for bean '" + beanName + "' with " + nrOfCommonInterceptors +
					" common interceptors and " + nrOfSpecificInterceptors + " specific interceptors");
		}

		Advisor[] advisors = new Advisor[allInterceptors.size()];
		for (int i = 0; i < allInterceptors.size(); i++) {
			advisors[i] = this.advisorAdapterRegistry.wrap(allInterceptors.get(i));
		}
		return advisors;
	}

	/**
	 * Resolves the specified interceptor names to Advisor objects.
	 * @see #setInterceptorNames
	 */
	private Advisor[] resolveInterceptorNames() {
		BeanFactory bf = this.beanFactory;
		ConfigurableBeanFactory cbf = (bf instanceof ConfigurableBeanFactory ? (ConfigurableBeanFactory) bf : null);
		List<Advisor> advisors = new ArrayList<>();
		for (String beanName : this.interceptorNames) {
			if (cbf == null || !cbf.isCurrentlyInCreation(beanName)) {
				Assert.state(bf != null, "BeanFactory required for resolving interceptor names");
				Object next = bf.getBean(beanName);
				advisors.add(this.advisorAdapterRegistry.wrap(next));
			}
		}
		return advisors.toArray(new Advisor[0]);
	}

	/**
	 * Subclasses may choose to implement this: for example,
	 * to change the interfaces exposed.
	 * <p>The default implementation is empty.
	 * @param proxyFactory a ProxyFactory that is already configured with
	 * TargetSource and interfaces and will be used to create the proxy
	 * immediately after this method returns
	 */
	protected void customizeProxyFactory(ProxyFactory proxyFactory) {
	}


	/**
	 * Return whether the given bean is to be proxied, what additional
	 * advices (e.g. AOP Alliance interceptors) and advisors to apply.
	 * @param beanClass the class of the bean to advise
	 * @param beanName the name of the bean
	 * @param customTargetSource the TargetSource returned by the
	 * {@link #getCustomTargetSource} method: may be ignored.
	 * Will be {@code null} if no custom target source is in use.
	 * @return an array of additional interceptors for the particular bean;
	 * or an empty array if no additional interceptors but just the common ones;
	 * or {@code null} if no proxy at all, not even with the common interceptors.
	 * See constants DO_NOT_PROXY and PROXY_WITHOUT_ADDITIONAL_INTERCEPTORS.
	 * @throws BeansException in case of errors
	 * @see #DO_NOT_PROXY
	 * @see #PROXY_WITHOUT_ADDITIONAL_INTERCEPTORS
	 */
	@Nullable
	protected abstract Object[] getAdvicesAndAdvisorsForBean(Class<?> beanClass, String beanName,
			@Nullable TargetSource customTargetSource) throws BeansException;

}
